#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "arbrehuffman.h"
#include "arbreCanonique.h"
#include "stringutils.h"
#include "binio.h"

/* Allocation d'une chaine de caractère constituée de deux élèment:
 * -une lettre
 * -un marqueur de fin de chaine \0
 */
char* allouerLetval() {
    char* res = calloc(2, sizeof (char));
    res[2] = '\0';
    return res;
}

void printTableaua(tableau* t) {
    LetVal * tab = t->tab;
    printf("Nombre: %d\n", t->nombre);
    for (int i = 0; i < t->nombre; i++) {
        printf("%s - %d\n", tab[i].lettre, tab[i].prof);
    }
}

/* Extrait le dictionnaire du début de fichier et fournit un arbre.
 * @param le fichier à traiter
 * @return l'arbre de huffman correspondant au codage.
 */
arbre* fromFile(FILE* fich) {
    int i, max;
    tableau* t = malloc(sizeof (tableau));
    t->nombre = 0;
    t->tab = (LetVal*) calloc(TAILLE_DICTIONNAIRE, sizeof (LetVal));

    fscanf(fich, " %d", & max);
    for (i = 0; i < max; i++) {
        t->tab[i].lettre = allouerLetval();
        t->tab[i].lettre[0] = fgetc(fich);
        fscanf(fich, " %d", & t->tab[i].prof);
        fgetc(fich);
        t->nombre++;
    }
    //On trie le tableau pour construire l'arbre selon les profondeurs 
    //et l'ordre alphabétique.
    triBulles(t);       
    printf("\n  --- Le tableau des longueur---\n");
    printTableaua(t);
    printf("\n  --- ---\n");
    return fromTableLongueur(t);
}

/* Decode le fichier binaire en entrée et retranscrit dans le fichier sortie
 * le texte decodé.
 * @param le fichier d'entrée et le fichier de sortie.
 */
void decoder_fichier(FILE* entree, FILE* sortie) {;
    printf("\n  ---Debut decodage---\n");
    binio_error_t err;
    binio_ulong_t val;
    int nombreCarRestant = 0;
    fscanf(entree, "%d",& nombreCarRestant);
    // On recupere le nombre de caractères.
    arbre* huff = fromFile(entree);
    //On construit l'arbre de huffman depuis le tableau des longueurs.
    printf("\n  ---L'arbre de Huffman ---\n");
    printarbre(huff, 0);
    arbre* courant = huff;  //On place notre pointeur sur la racine de l'arbre.
    char lettre;
    //Initialisation de binio pour la lecture binaire du fichier d'entrée.
    binio_init(2);
    binio_t lect = binio_read_open((binio_fgetc_t *) fgetc,
            (binio_eof_t *) feof,
            (binio_file_func_param_t) entree,
            1);

    do {// Pour chaque bits:
        err = binio_unsigned_read(lect, &val, 1, 0);
        if (val)//parcours de l'arbre soit à gauche
            courant = courant->gch;
        else //Soit à droite.
            courant = courant->dte;

        if (courant->dte == NULL && courant->gch == NULL) { //Si feuille:
            lettre = courant->lettre[0];
            printf("lettre trouve : %c \n", lettre);
            // On écris le résultat dans le fichier.
            fprintf(sortie, "%c", lettre);  
            courant = huff;     
            // On replace le pointeur sur la racine et on recomence.
            nombreCarRestant--;
        }
        
    } while (err != -1 && nombreCarRestant > 0);

    binio_close(lect);
    fflush(sortie);
    printf("fin_decoder_fichier\n");
}
